﻿#define _CRT_SECURE_NO_WARNINGS 1

//构造函数与析构函数



//构造函数的主要任务并不是开空间创建对象(我们常使⽤的局部对象是栈帧创建时，空间就开好了)，⽽是对象实例化时初始化对象。
//构造函数⾃动调⽤的特点就完美的替代的了Init。

//构造函数的特点:
//1. 函数名与类名相同。
//2. ⽆返回值。
//3. 对象实例化时系统会⾃动调⽤对应的构造函数。
//4. 构造函数可以重载。
//5. 如果类中没有显式定义构造函数，则C++编译器会⾃动⽣成⼀个⽆参的默认构造函数，⼀旦⽤⼾显式定义编译器将不再⽣成。
//6、只能存在一个默认构造函数否则调用时存在歧义
//7、编译器默认的构造对内置类型成员变量的初始化没有要求 对于⾃定义类型成员变量，要调⽤这个成员变量的默认构造函数初始化。

#include <iostream>
using namespace std;


//在之前我们每次实例化对象后都需要初始化 构造函数则赋予了自动初始化的这一特点
class Date
{
public:
	//无参数构造函数 全缺省构造函数 和编译器默认生成的构造函数都叫默认构造函数
	/*Date()
	{
		_year = 1;
		_month = 1;
		_day = 1;
	}*/

	//Date(int year,int month, int day)  //不是全缺省构造函数 因此不是默认构造函数 会报错
	//{
	//	_year = year;
	//	_month = month;
	//	_day = day;
	//}

	Date(int year = 2025, int month = 5, int day = 11)
	{
		_year = year;
		_month = month;
		_day = day;
	}

	void Print()
	{
		cout << _year << "/" << _month << "/" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

//int main()
//{
//	/*Date d1;   //在实例化对象d1后，默认初始化为1/1/1 不再需要执行d1.Init();
//	d1.Print();*/  
//
//	/*Date d2;
//	d2.Print();*/
//
//	/*Date d2(2024,1,5);
//	d2.Print();*/
//
//	/*Date d3;
//	d3.Print();*/
//
//	/*Date d3(2025, 2, 4);
//	d3.Print();*/
//
//
//	return 0;
//}


//析构函数


//析构函数不是完成对对象本⾝的销毁， 完成对象中资源的清理释放⼯作
//析构函数的功能类⽐我们之前Stack实现的Destroy功能，⽽像Date没有Destroy，其实就是没有资源需要释放，所以严格说Date是不需要析构函数的


//析构函数的特点：
//1. 析构函数名是在类名前加上字符 ~。
//2. ⽆参数⽆返回值。
//3. ⼀个类只能有⼀个析构函数。若未显式定义，系统会⾃动⽣成默认的析构函数。
//4. 对象⽣命周期结束时，系统会⾃动调⽤析构函数。
//5. 编译器⾃动⽣成的析构函数对内置类型成员不做处理，⾃定类型成员会调⽤他的析构函数。
//6. 我们显式写析构函数，对于⾃定义类型成员也会调⽤他的析构，也就是说⾃定义类型成员⽆论什么情况都会⾃动调⽤析构函数。
//7. 如果类中没有申请资源时，析构函数可以不写，直接使⽤编译器⽣成的默认析构函数，如Date；如
//果默认⽣成的析构就可以⽤，也就不需要显⽰写析构，如MyQueue；但是有资源申请时，⼀定要⾃⼰写析构，否则会造成资源泄漏，如Stack。

typedef int STDataType;
class Stack
{
public:
	Stack(int n = 4) //栈这个类的构造函数
	{

		_a = (STDataType*)malloc(sizeof(STDataType) * n);  //动态开辟的，最后需要析构函数
		if (nullptr == _a)
		{
			perror("malloc申请空间失败");
			return;
		}
		_capacity = n;  //构造函数默认初始化_capacity=4 _top=0
		_top = 0;
	}

	~Stack()  //析构函数  函数栈帧销毁后会自动调用
	{
		free(_a);  //释放开辟的空间
		_a = nullptr;
		_top = _capacity = 0;
	}

private:
	STDataType* _a;
	size_t _capacity;
	size_t _top;
};


//用两个栈实现一个队列
class MyQueue
{
	//由于成员变量均为自定义类型,默认构造和默认析构都会调用栈的构造和析构
	//因此这里不需要写出构造函数和析构函数
public:
	~MyQueue()
	{
		cout << "~MyQueue()" << endl;
	}
private:
	Stack _pushst;
	Stack _popst;
};

int main()
{
	/*Stack st1(4);*/  //进入调试观察st1 可以发现先执行构造函数  函数结束后执行析构函数

	MyQueue mq1;  //执行后发现析构函数执行
	//同时发现自己写的~MyQueue析构函数和自定义类型的成员变量对应的析构函数都会执行，并且先执行~MyQueue再执行~Stack
	return 0;
}